use serde::{Deserialize, Serialize};

use super::{link::LinkForm, tag::TagForm};
use crate::database::{self, table::post::model::NewPost};

#[derive(Debug, Serialize, Deserialize)]
pub struct PostForm {
    pub id: i32,
    pub title: String,
    pub cover: String,
    pub tid: i32,
    pub sid: String,
    pub tids: Vec<i32>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NewPostForm {
    pub title: String,
    pub cover: String,
    pub tid: i32,
    pub sid: String,
    pub tids: Vec<i32>,
}

impl From<&database::table::post::model::Post> for PostForm {
    fn from(post: &database::table::post::model::Post) -> Self {
        PostForm {
            id: post.id,
            title: post.title.to_string(),
            cover: post.cover.to_string(),
            tid: post.tid,
            sid: post.sid.to_string(),
            tids: post
                .tids
                .split(',')
                .into_iter()
                .filter_map(|tag| tag.parse::<i32>().ok())
                .collect(),
        }
    }
}

impl PostForm {
    pub fn to(&self) -> NewPostForm {
        NewPostForm {
            title: self.title.to_string(),
            cover: self.cover.to_string(),
            tid: self.tid,
            sid: self.sid.to_string(),
            tids: self.tids.clone(),
        }
    }
}

impl NewPostForm {
    pub fn to(&self) -> NewPost {
        NewPost {
            title: &self.title,
            cover: &self.cover,
            tid: self.tid,
            sid: &self.sid,
            tids: self
                .tids
                .iter()
                .map(|tid| tid.to_string())
                .collect::<Vec<String>>()
                .join(","),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WritePostForm {
    pub title: String,
    pub cover: String,
    pub author: i32,
    pub tags: Vec<i32>,
    pub images: Vec<String>,
}

impl WritePostForm {
    pub fn to(&self, sid: &String) -> NewPostForm {
        NewPostForm {
            title: self.title.clone(),
            cover: self.cover.clone(),
            tid: self.author,
            sid: sid.clone(),
            tids: self.tags.clone(),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ViewPostForm {
    pub post: PostForm,
    pub tags: Vec<TagForm>,
    pub author: TagForm,
    pub links: Vec<LinkForm>,
    pub images: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PreviewPostForm {
    pub post: PostForm,
    pub author: TagForm,
}

impl From<&database::view::post_with_author::PostWithAuthor> for PreviewPostForm {
    fn from(post_with_author: &database::view::post_with_author::PostWithAuthor) -> Self {
        PreviewPostForm {
            post: PostForm::from(&post_with_author.post),
            author: TagForm::from(&post_with_author.author),
        }
    }
}
